home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / sbin / laptop_mode < prev    next >
Encoding:
Text File  |  2012-05-20  |  43.1 KB  |  1,200 lines

  1. #! /bin/sh
  2. #
  3. # Script to start or stop laptop_mode, and to control various settings of the
  4. # kernel, hardware etc. that influence power consumption.
  5. #
  6. # This script is a part of Laptop Mode Tools. If you are running a supported
  7. # power management daemon, this script will be automatically called on power
  8. # state change.
  9. #
  10. # Configure laptop mode tools in /etc/laptop-mode/laptop-mode.conf, and in
  11. # the broken-out config files in /etc/laptop-mode/conf.d.
  12. #
  13. # Please consult the manual pages laptop-mode.conf(8) and laptop_mode(8) for
  14. # additional information.
  15. #
  16. # Maintainer:             Ritesh Raj Sarraf (rrs@researchut.com)
  17. # Original Author:        Bart Samwel (bart@samwel.tk)
  18. # Project home page: http://samwel.tk/laptop_mode
  19. #
  20. # Contributors to this script:   Bart Samwel
  21. #                 Kiko Piris
  22. #                 Micha Feigin
  23. #                 Andrew Morton
  24. #                 Herve Eychenne
  25. #                 Dax Kelson
  26. #                 Jan Polacek
  27. #                 ... and many others that I've stopped
  28. #                 keeping track of.
  29. #
  30. # Based on a script for Linux 2.4 written by Jens Axboe.
  31. #
  32. #############################################################################
  33.  
  34. set -a
  35.  
  36. # The laptop mode tools version number. Extracted by the installer makefile
  37. # as well, so don't change the format!
  38. LMTVERSION=1.61
  39.  
  40. # This script is loaded from multiple scripts to set the config defaults
  41. # and to read the configuration on top of those. Only when the command is
  42. # recognized does this script do anything else.
  43. VERBOSE_OUTPUT=0
  44. ENABLE_LAPTOP_MODE_ON_BATTERY=1
  45. ENABLE_LAPTOP_MODE_ON_AC=0
  46. ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED=0
  47. PARTITIONS="auto /dev/mapper/*"
  48. LM_BATT_MAX_LOST_WORK_SECONDS=600
  49. LM_AC_MAX_LOST_WORK_SECONDS=360
  50. DEF_MAX_AGE=30
  51. LM_READAHEAD=3072
  52. NOLM_READAHEAD=128
  53. CONTROL_READAHEAD=1    
  54. CONTROL_NOATIME=0
  55. USE_RELATIME=1
  56. CONTROL_HD_IDLE_TIMEOUT=1
  57. LM_AC_HD_IDLE_TIMEOUT=4    # 20 seconds
  58. LM_BATT_HD_IDLE_TIMEOUT=4  # 20 seconds
  59. NOLM_HD_IDLE_TIMEOUT=244   # 2 hours
  60. DEF_UPDATE=5
  61. DEF_XFS_AGE_BUFFER=15
  62. DEF_XFS_SYNC_INTERVAL=30
  63. DEF_XFS_BUFD_INTERVAL=1
  64. XFS_HZ=100
  65. CONTROL_MOUNT_OPTIONS=1
  66. BATT_HD_POWERMGMT=1
  67. LM_AC_HD_POWERMGMT=254
  68. NOLM_AC_HD_POWERMGMT=254
  69. CONTROL_HD_POWERMGMT=0
  70. CONTROL_HD_WRITECACHE=0
  71. NOLM_AC_HD_WRITECACHE=1
  72. NOLM_BATT_HD_WRITECACHE=0
  73. LM_HD_WRITECACHE=0
  74. LM_DIRTY_RATIO=60
  75. LM_DIRTY_BACKGROUND_RATIO=1
  76. NOLM_DIRTY_BACKGROUND_RATIO=10
  77. NOLM_DIRTY_RATIO=40
  78. LM_SECONDS_BEFORE_SYNC=2    
  79. BATT_CPU_MAXFREQ=medium
  80. BATT_CPU_MINFREQ=slowest
  81. BATT_CPU_GOVERNOR=ondemand
  82. BATT_CPU_IGNORE_NICE_LOAD=1
  83. LM_AC_CPU_MAXFREQ=fastest
  84. LM_AC_CPU_MINFREQ=slowest
  85. LM_AC_CPU_GOVERNOR=ondemand
  86. LM_AC_CPU_IGNORE_NICE_LOAD=1
  87. NOLM_AC_CPU_MAXFREQ=fastest
  88. NOLM_AC_CPU_MINFREQ=slowest
  89. NOLM_AC_CPU_GOVERNOR=ondemand
  90. NOLM_AC_CPU_IGNORE_NICE_LOAD=0
  91. CONTROL_CPU_FREQUENCY=0
  92. HD="/dev/[hs]d[abcdefgh]"
  93. CONTROL_SYSLOG_CONF=0
  94. LM_AC_SYSLOG_CONF=/etc/syslog-on-ac-with-lm.conf
  95. NOLM_AC_SYSLOG_CONF=/etc/syslog-on-ac-without-lm.conf
  96. BATT_SYSLOG_CONF=/etc/syslog-on-battery.conf
  97. SYSLOG_CONF_SIGNAL_PROGRAM=syslogd
  98. SYSLOG_CONF=/etc/syslog.conf
  99. CONTROL_DPMS_STANDBY=0
  100. BATT_DPMS_STANDBY=300
  101. LM_AC_DPMS_STANDBY=1200
  102. NOLM_AC_DPMS_STANDBY=1200
  103. CONTROL_CPU_THROTTLING=0
  104. BATT_CPU_THROTTLING=medium
  105. LM_AC_CPU_THROTTLING=minimum
  106. NOLM_AC_CPU_THROTTLING=minimum
  107. CONTROL_START_STOP=1
  108. CONTROL_TERMINAL=0
  109. TERMINALS="/dev/vc/1 /dev/vcs1"
  110. BATT_TERMINAL_BLANK_MINUTES=1
  111. BATT_TERMINAL_POWERDOWN_MINUTES=2
  112. LM_AC_TERMINAL_BLANK_MINUTES=10
  113. LM_AC_TERMINAL_POWERDOWN_MINUTES=10
  114. NOLM_AC_TERMINAL_BLANK_MINUTES=10
  115. NOLM_AC_TERMINAL_POWERDOWN_MINUTES=50
  116. ENABLE_AUTO_HIBERNATION=0
  117. HIBERNATE_COMMAND=/usr/sbin/hibernate
  118. AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL=1
  119. DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL=1
  120. AUTO_HIBERNATION_BATTERY_CHARGE_MAH=0
  121. AUTO_HIBERNATION_BATTERY_CHARGE_MWH=0
  122. MINIMUM_BATTERY_CHARGE_MAH=0
  123. MINIMUM_BATTERY_CHARGE_MWH=0
  124. ASSUME_SCSI_IS_SATA=1
  125. CONTROL_BRIGHTNESS=0
  126. BATT_BRIGHTNESS_COMMAND=false
  127. LM_AC_BRIGHTNESS_COMMAND=false
  128. NOLM_AC_BRIGHTNESS_COMMAND=false
  129. LOG_TO_SYSLOG=1
  130. DEBUG=0
  131. ENABLE_LAPTOP_MODE_TOOLS=1
  132.  
  133. # Initialize the PATH Variable
  134. export PATH="${PATH}":/bin:/sbin:/usr/bin:/usr/sbin
  135.  
  136. # This is a 2 phase locking approach. LMT_REQ_LOCK is the outer lock and LMT_INVOC_LOCK is the inner lock
  137. # We take this approach to ensure the scenario that, "At any point when an event occurs (AC/BATT), the
  138. # kernel can generate multiple events spanning over a couple of events. The first event is honored and
  139. # lmt executes. If the last event triggered at the 9th second, there is a fair chance that a good amount
  140. # of state change would have occured in the OS, to honor that state, we keep an outer lock  (LMT_REQ_LOCK)
  141. # handy, so that those changes can also be applied and not forgotten.
  142. # Workflow:
  143. # Event-1 is generated and lmt executes (lmt runtime could span 5-10 seconds)
  144. # At seventh second, 4 events generate. But Event-1 is still running.
  145. # We don't want to discard all the remaining 4 events, but at least honor 1 so that we can act to the changes
  146. # that occured in the last 7 seconds.
  147. # So, Event-2 acquire LMT_REQ_LOCK and waits to acquire LMT_INVOC_LOCK (which is acquire by Event-1)
  148. LMT_REQ_LOCK="/var/lock/lmt-req.lock"
  149. LMT_INVOC_LOCK="/var/lock/lmt-invoc.lock"
  150. LMT_BATTPOLL_LOCK="/var/lock/lmt-battpoll.lock"
  151. FLOCK=`which flock`
  152.  
  153. checkint ()
  154. {
  155.     # $1 arg should be the string/integer
  156.     # that you want to check for as an integer.
  157.     echo $1 | grep "[^0-9]" > /dev/null 2>&1
  158.  
  159.     return $?;
  160.     # Returns 1 if it is an integer
  161. }
  162.  
  163. # Function to handle logging
  164. LOGGER=`which logger`;
  165.  
  166. log ()
  167. {
  168. # $1 should be msg type
  169. # $2 should be the real msg
  170. if [ x$LOG_TO_SYSLOG = x1 ]; then
  171.     # NOTE: Add the check on $2 being empty, once you are confident
  172.     # that there aren't any bugs in logging. And no bugs in executing 
  173.     # modules and logging
  174.     if [ -x $LOGGER -a "$1" != "STATUS" ]; then
  175.         #if [ -z $2 ]; then
  176.         #    continue
  177.         #elif [ "$1" = "MSG" ]; then
  178.         if [ "$1" = "MSG" ]; then
  179.             logger -p daemon.info -t laptop-mode "$2";
  180.         elif [ "$1" = "ERR" ]; then
  181.             logger -p daemon.err -t laptop-mode "$2";
  182.         elif [ "$1" = "VERBOSE" ]; then
  183.         if [ x$VERBOSE_OUTPUT = x1 ]; then
  184.                     logger -p daemon.debug -t laptop-mode "$2";
  185.         fi
  186.         else
  187.             logger -p daemon.notice -t laptop-mode "$2";
  188.         fi
  189.     fi
  190. fi
  191.  
  192. if [ "$1" = "VERBOSE" ]; then
  193.     $LM_VERBOSE &&  echo "$2" >/dev/fd/2;
  194. elif [ "$1" = "ERR" ]; then
  195.     echo "$2" >/dev/fd/2;
  196. else
  197.     # Message of type MSG and STATUS can go to stdout.
  198.     echo "$2" >/dev/fd/1;
  199. fi
  200. }
  201.  
  202. enableDebug ()
  203. {
  204.         # Check if debug is enabled
  205.         if [ x$(($(basename $1 | cut -d . -f1 | tr "[:lower:]" "[:upper:]" | sed 's/-/_/g')_DEBUG)) = x1 ]; then
  206.                 set -vx
  207.         fi
  208. }
  209.  
  210. disableDebug ()
  211. {
  212.         # Check if debug is enabled
  213.         if [ x$(($(basename $1 | cut -d . -f1 | tr "[:lower:]" "[:upper:]" | sed 's/-/_/g')_DEBUG)) = x1 ]; then
  214.                 set +vx
  215.         fi
  216. }
  217.  
  218. # No default on these ones -- we need to detect if they have been set, for
  219. # backward compatibility with MINIMUM_BATTERY_MINUTES etc.
  220. AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT=
  221. MINIMUM_BATTERY_CHARGE_PERCENT=
  222.  
  223. # Backward compatibility variable that is sometimes
  224. # set externally (Debian init system)
  225. unset VERBOSE
  226.  
  227. lmt_load_config ()
  228. {
  229.     # Source config. Some config settings have been moved from the main config file
  230.     # to modular configuration files, and to support existing laptop-mode.conf
  231.     # files from earlier versions, we source the modular configuration files FIRST.
  232.     if [ -d /etc/laptop-mode/conf.d ] ; then
  233.         for CONF in /etc/laptop-mode/conf.d/*.conf /etc/laptop-mode/conf.d/board-specific/*.conf; do
  234.             if [ -r "$CONF" ] ; then
  235.                 . "$CONF"
  236.                 #Handle individual module debug settings
  237.                 if [ "$DEBUG" -eq 1 ]; then
  238.                     export $(basename $CONF | cut -d . -f1 | tr "[:lower:]" "[:upper:]" | sed 's/-/_/g')_DEBUG=1
  239.                     log "VERBOSE" "Enabling debug mode for module $CONF"
  240.                 fi
  241.                 DEBUG=0
  242.             else
  243.                 log "MSG" "Warning: Configuration file $CONF is not readable, skipping."
  244.             fi
  245.         done
  246.     fi
  247.     if [ -r /etc/laptop-mode/laptop-mode.conf ] ; then
  248.         . /etc/laptop-mode/laptop-mode.conf
  249.     else
  250.         log "ERR" "$0: Configuration file /etc/laptop-mode/laptop-mode.conf not present or not readable."
  251.         exit 1
  252.     fi
  253.  
  254.     if [ x$ENABLE_LAPTOP_MODE_TOOLS = x0 ]; then
  255.         log "MSG" "laptop-mode-tools is disabled in config file. Exiting"
  256.         exit 0;
  257.     fi
  258.  
  259.     # Add a simple bash debug mode switch
  260.     if [ "$DEBUG" -eq 1 ]; then
  261.     set -vx;
  262.     fi
  263.  
  264.     # Support for old config settings
  265.     if [ "$AC_HD" != "" ] ; then
  266.         AC_HD_WITHOUT_LM="$AC_HD"
  267.         AC_HD_WITH_LM="$AC_HD"
  268.     fi
  269.     if [ "$VERBOSE" != "" ] ; then
  270.         VERBOSE_OUTPUT="$VERBOSE"
  271.     fi
  272.     if [ "$CPU_MAXFREQ" != "" ] ; then
  273.         BATT_CPU_MAXFREQ="$CPU_MAXFREQ"
  274.     fi
  275.     if [ "$MAX_AGE" != "" ] ; then
  276.         LM_BATT_MAX_LOST_WORK_SECONDS="$MAX_AGE"
  277.         LM_AC_MAX_LOST_WORK_SECONDS="$MAX_AGE"
  278.     fi
  279.     if [ "$DEF_AGE" != "" ] ; then
  280.         DEF_MAX_AGE="$DEF_AGE"
  281.     fi
  282.     if [ "$LAPTOP_MODE_ALWAYS_ON" != "" ] ; then
  283.         ENABLE_LAPTOP_MODE_ALWAYS="$LAPTOP_MODE_ALWAYS_ON"
  284.     fi
  285.     if [ "$LM_WHEN_LID_CLOSED" != "" ] ; then
  286.         ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED="$LM_WHEN_LID_CLOSED"
  287.     fi
  288.     if [ "$REMOUNT_PARTITIONS" != "" ] ; then
  289.         PARTITIONS="$REMOUNT_PARTITIONS"
  290.     fi
  291.     if [ "$READAHEAD" != "" ] ; then
  292.         LM_READAHEAD="$READAHEAD"
  293.     fi
  294.     if [ "$DO_REMOUNT_NOATIME" != "" ] ; then
  295.         CONTROL_NOATIME="$DO_REMOUNT_NOATIME"
  296.     fi
  297.     if [ "$DO_HD" != "" ] ; then
  298.         CONTROL_HD_IDLE_TIMEOUT="$DO_HD"
  299.     fi
  300.     if [ "$AC_HD_WITH_LM" != "" ] ; then
  301.         LM_AC_HD_IDLE_TIMEOUT="$AC_HD_WITH_LM"
  302.     fi
  303.     if [ "$AC_HD_WITHOUT_LM" != "" ] ; then
  304.         NOLM_HD_IDLE_TIMEOUT="$AC_HD_WITHOUT_LM"
  305.     fi
  306.     if [ "$BATT_HD" != "" ] ; then
  307.         LM_BATT_HD_IDLE_TIMEOUT="$BATT_HD"
  308.     fi        
  309.     if [ "$DO_REMOUNTS" != "" ] ; then
  310.         CONTROL_MOUNT_OPTIONS="$DO_REMOUNTS"
  311.     fi    
  312.     if [ "$DO_HD_POWERMGMT" != "" ] ; then
  313.         CONTROL_HD_POWERMGMT="$DO_HD_POWERMGMT"
  314.     fi
  315.     if [ "$AC_HDPARM_POWERMGMT_WITH_LM" != "" ] ; then
  316.         LM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITH_LM"
  317.     fi
  318.     if [ "$AC_HDPARM_POWERMGMT_WITHOUT_LM" != "" ] ; then
  319.         NOLM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITHOUT_LM"
  320.     fi
  321.     if [ "$BATT_HDPARM_POWERMGMT" != "" ] ; then
  322.         BATT_HD_POWERMGMT="$BATT_HDPARM_POWERMGMT"
  323.     fi
  324.     if [ "$DO_WRITECACHE" != "" ] ; then
  325.         CONTROL_HD_WRITECACHE="$DO_WRITECACHE"
  326.     fi
  327.     if [ "$AC_WRITECACHE_WITHOUT_LM" != "" ] ; then
  328.         NOLM_AC_HD_WRITECACHE="$AC_WRITECACHE_WITHOUT_LM"
  329.     fi
  330.     if [ "$BATT_WRITECACHE" != "" ] ; then
  331.         LM_HD_WRITECACHE="$BATT_WRITECACHE"
  332.     fi
  333.     if [ "$DIRTY_RATIO" != "" ]; then
  334.         LM_DIRTY_RATIO="$DIRTY_RATIO"
  335.     fi
  336.     if [ "$DIRTY_BACKGROUND_RATIO" != "" ] ; then
  337.         LM_DIRTY_BACKGROUND_RATIO="$DIRTY_BACKGROUND_RATIO"
  338.     fi
  339.     if [ "$DEF_DIRTY_RATIO" != "" ]; then
  340.         NOLM_DIRTY_RATIO="$DEF_DIRTY_RATIO"
  341.     fi
  342.     if [ "$DEF_DIRTY_BACKGROUND_RATIO" != "" ] ; then
  343.         NOLM_DIRTY_BACKGROUND_RATIO="$DEF_DIRTY_BACKGROUND_RATIO"
  344.     fi
  345.     if [ "$DO_CPU" != "" ] ; then
  346.         CONTROL_CPU_FREQUENCY="$DO_CPU"
  347.     fi
  348.     if [ "$CONTROL_CPU_MAXFREQ" != "" ] ; then
  349.         CONTROL_CPU_FREQUENCY="$CONTROL_CPU_MAXFREQ"
  350.     fi
  351.     if [ "$AC_CPU_MAXFREQ_WITH_LM" != "" ] ; then
  352.         LM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITH_LM"
  353.     fi
  354.     if [ "$AC_CPU_MAXFREQ_WITHOUT_LM" != "" ] ; then
  355.         NOLM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITHOUT_LM"
  356.     fi
  357.     if [ "$DO_SYSLOG" != "" ] ; then
  358.         CONTROL_SYSLOG_CONF="$DO_SYSLOG"
  359.     fi
  360.     if [ "$SYSLOG_SIGNAL_PROGRAM" != "" ] ;then
  361.         SYSLOG_CONF_SIGNAL_PROGRAM="$SYSLOG_SIGNAL_PROGRAM"
  362.     fi
  363.     if [ "$AC_SYSLOG_WITH_LM" != "" ] ; then
  364.         LM_AC_SYSLOG_CONF="$AC_SYSLOG_WITH_LM"
  365.     fi
  366.     if [ "$AC_SYSLOG_WITHOUT_LM" != "" ] ; then
  367.         NOLM_AC_SYSLOG_CONF="$AC_SYSLOG_WITHOUT_LM"
  368.     fi
  369.     if [ "$BATT_SYSLOG" != "" ] ; then
  370.         BATT_SYSLOG_CONF="$BATT_SYSLOG"
  371.     fi
  372.     if [ "$ENABLE_LAPTOP_MODE_ALWAYS" != "" ] ; then
  373.         ENABLE_LAPTOP_MODE_ON_AC="$ENABLE_LAPTOP_MODE_ALWAYS"
  374.     fi
  375.     if [ "$MINIMUM_BATTERY_MINUTES" != "" -a "$MINIMUM_BATTERY_CHARGE_PERCENT" = "" ] ; then
  376.         # Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery)
  377.         # for backward compatibility.
  378.         MINIMUM_BATTERY_CHARGE_PERCENT="$MINIMUM_BATTERY_MINUTES"
  379.     fi
  380.     if [ -z "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
  381.         # Apply the default, now that we've determined that this is the minimum.
  382.         MINIMUM_BATTERY_CHARGE_PERCENT=3
  383.     fi
  384.     if [ "$AUTO_HIBERNATION_BATTERY_MINUTES" != "" -a "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" = "" ] ; then
  385.         # Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery)
  386.         # for backward compatibility.
  387.         AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT="$AUTO_HIBERNATION_BATTERY_MINUTES"
  388.     fi
  389.     if [ -z "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
  390.         # Apply the default, now that we've determined that this is the minimum.
  391.         AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT=2
  392.     fi
  393.  
  394.     # Postprocessing
  395.     if [ "$VERBOSE_OUTPUT" -ne 0 ] ; then
  396.         OUTPUT="/dev/stdout"
  397.         LM_VERBOSE="[ 1 = 1 ]"
  398.     else
  399.         OUTPUT="/dev/null"
  400.         LM_VERBOSE="[ 1 = 0 ]"
  401.     fi
  402.  
  403.     if [ "$PARTITIONS" = "" ] ; then
  404.         PARTITIONS="auto /dev/mapper/*"
  405.     fi
  406.  
  407.  
  408.     # Expand shell wild cards immediately.
  409.     PARTITIONS=$( echo $PARTITIONS )
  410.     TERMINALS=$( echo $TERMINALS )
  411.  
  412.     # Convert seconds to hdparm -S format
  413.     # Everything over 20 minutes is interpreted as 2 hours.
  414.     seconds_to_hdparm_S() {
  415.       if [ "$1" -eq 0 ] ; then
  416.         # disable.
  417.         echo 0
  418.     elif [ "$1" -gt 0 -a "$1" -lt 5 ] ; then
  419.         # 5 seconds minimum
  420.         echo 1     
  421.       elif [ "$1" -le $((240*5)) ] ; then
  422.         # Values between 1 and 240 signify increments of 5 seconds
  423.         echo $(($1 / 5))
  424.       elif [ "$1" -lt $((30*60)) ] ; then
  425.         # Values between 20 and 30 minutes are rounded up to 30 minutes.
  426.         echo 241
  427.       elif [ "$1" -lt $((12*30*60)) ] ; then
  428.         # Values between 30 minutes and 6 hours (exclusive) yield values between
  429.         # 241 and 251, in 30-minute increments.
  430.         echo $(( 240 + ($1 / (30*60)) ))
  431.       else
  432.         # Larger values effectively indicate no timeout at all.
  433.         echo 0
  434.       fi
  435.     }
  436.  
  437.     # Convert configured idle timeouts to hdparm -S format.
  438.     if [ "$LM_AC_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
  439.         LM_AC_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_AC_HD_IDLE_TIMEOUT_SECONDS)
  440.     fi
  441.     if [ "$LM_BATT_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
  442.         LM_BATT_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_BATT_HD_IDLE_TIMEOUT_SECONDS)
  443.     fi
  444.     if [ "$NOLM_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
  445.         NOLM_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $NOLM_HD_IDLE_TIMEOUT_SECONDS)
  446.     fi
  447.  
  448.  
  449.  
  450.     # Determine the power state.
  451.  
  452.     # First try /sys/class/power_supply/*
  453.     FOUND_SYS_CLASS_POWER_SUPPLY_AC=0
  454.     export ON_AC=0
  455.     for POWER_SUPPLY in /sys/class/power_supply/* ; do
  456.         if [ -f $POWER_SUPPLY/type ] ; then
  457.             if [ "$(cat $POWER_SUPPLY/type)" = "Mains" ] ;then
  458.                 log "VERBOSE" "Determining power state from $POWER_SUPPLY/online."
  459.                 FOUND_SYS_CLASS_POWER_SUPPLY_AC=1
  460.                 if [ "$(cat $POWER_SUPPLY/online)" = 1 ] ; then
  461.                     ON_AC=1
  462.                 fi
  463.             fi
  464.         fi
  465.     done
  466.  
  467.     if [ $FOUND_SYS_CLASS_POWER_SUPPLY_AC = 1 ] ; then
  468.         # Already found it!
  469.         log "VERBOSE" "Not trying other options, already found a power supply."
  470.     elif [ -d /proc/acpi/ac_adapter ] ; then
  471.         log "VERBOSE" "Determining power state from /proc/acpi/ac_adapter."
  472.         ADAPTERS_FOUND=0
  473.         ON_AC=0
  474.         for ADAPTER in /proc/acpi/ac_adapter/* ; do
  475.             if [ -f $ADAPTER/state ] ; then
  476.                 ADAPTERS_FOUND=1
  477.                 STATUS=`awk '/^state: / { print $2 }' $ADAPTER/state`
  478.                 if [ "$STATUS" = "on-line" ] ; then
  479.                     ON_AC=1
  480.                 fi
  481.             fi
  482.         done
  483.         if [ "$ADAPTERS_FOUND" -eq 0 ] ; then
  484.             ON_AC=1
  485.         fi
  486.     elif [ -f /proc/pmu/info ] ; then
  487.         log "VERBOSE" "Determining power state from /proc/pmu/info."
  488.         if ( grep -q "^AC Power.*0$" /proc/pmu/info ) ; then
  489.             log "VERBOSE" "/proc/pmu/info indicates absence of AC power."
  490.             ON_AC=0
  491.         else
  492.             # It is possible that there is no AC Power = 1 in the file,
  493.             # but we always assume AC power when we're not sure.
  494.             ON_AC=1
  495.             log "VERBOSE" "/proc/pmu/info indicates presence of AC power."
  496.         fi
  497.     elif [ -f /proc/apm ] ; then
  498.         log "VERBOSE" "Determining power state from /proc/apm."
  499.         read D1 D2 D3 APM_AC_STATE D0 </proc/apm
  500.         if [ "$APM_AC_STATE" = "0x00" ] ; then
  501.             ON_AC=0
  502.         else
  503.             ON_AC=1
  504.         fi
  505.     else
  506.         log "VERBOSE" "No /sys/class/power_supply, ACPI, APM or PMU power management information found -- assuming AC power is present."
  507.         ON_AC=1
  508.     fi
  509.  
  510. }
  511.  
  512.  
  513. # The main workhorse.
  514. lmt_main_function ()
  515. {
  516.     if [ "$1" = "status" ] ; then
  517.         # Display a status report.
  518.         log "STATUS" "Mounts:"
  519.         mount | sed "s/^/   /"
  520.         log "STATUS" " "
  521.         log "STATUS" "Drive power status:"
  522.         for disk in $HD; do
  523.             if [ -r $disk ]; then
  524.                 hdparm -C $disk 2>/dev/null | sed "s/^/   /"
  525.             else
  526.                 log "STATUS" "   Cannot read $disk, permission denied - $0 needs to be run as root"
  527.             fi
  528.         done
  529.         log "STATUS" " "
  530.         log "STATUS" "(NOTE: drive settings affected by Laptop Mode cannot be retrieved.)"
  531.  
  532.         log "STATUS" " "
  533.         log "STATUS" "Readahead states:"
  534.         cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
  535.             # skip funny stuff
  536.             case "$FST" in 
  537.               rootfs|unionfs|tmpfs|squashfs|sysfs|usbfs|proc|devpts) continue
  538.               ;;
  539.             esac
  540.             if [ -b $DEV ] ; then
  541.                 if [ -r $DEV ] ; then
  542.                     log "STATUS" "   $DEV: $((`blockdev --getra $DEV` / 2)) kB"
  543.                 else
  544.                     log "STATUS" "   Cannot read $DEV, permission denied - $0 needs to be run as root"
  545.                 fi
  546.             fi
  547.         done
  548.         log "STATUS" " "
  549.         if [ -e /var/run/laptop-mode-tools/enabled ] ; then
  550.             log "STATUS" "Laptop Mode Tools is allowed to run: /var/run/laptop-mode-tools/enabled exists."
  551.         else
  552.             log "STATUS" "Laptop Mode Tools is NOT allowed to run: /var/run/laptop-mode-tools/enabled does not exist."
  553.         fi
  554.     log "STATUS" " "
  555.         STATFILES="/proc/sys/vm/laptop_mode /proc/apm /proc/pmu/info /proc/sys/vm/bdflush /proc/sys/vm/dirty_ratio /proc/sys/fs/xfs/age_buffer /proc/sys/fs/xfs/sync_interval /proc/sys/fs/xfs/lm_age_buffer /proc/sys/fs/xfs/lm_sync_interval /proc/sys/vm/pagebuf/lm_flush_age /proc/sys/fs/xfs/xfsbufd_centisecs /proc/sys/fs/xfs/xfssyncd_centisecs /proc/sys/vm/dirty_background_ratio /proc/sys/vm/dirty_expire_centisecs /proc/sys/fs/xfs/age_buffer/centisecs /proc/sys/vm/dirty_writeback_centisecs /sys/devices/system/cpu/*/cpufreq/cpuinfo_*_freq /sys/devices/system/cpu/*/cpufreq/scaling_governor /proc/acpi/button/lid/*/state /proc/acpi/ac_adapter/*/state /proc/acpi/battery/*/state /sys/class/power_supply/*/online /sys/class/power_supply/*/state"
  556.         for THISFILE in $STATFILES ; do
  557.             if [ -e "$THISFILE" ] ; then
  558.                 log "STATUS" "$THISFILE:"
  559.                 if [ -r "$THISFILE" ] ; then
  560.                     cat "$THISFILE" | sed "s/^/   /"
  561.                 else
  562.                     log "STATUS" "   Not accessible, permission denied - $0 needs to be run as root."
  563.                 fi
  564.                 log "STATUS" " "
  565.             fi
  566.         done
  567.  
  568.     elif [ "$1" != "readconfig" -a "$1" != "defaults" ] ; then
  569.  
  570.     #############################################################################
  571.  
  572.     KLEVEL="$(uname -r |
  573.                 {
  574.                     IFS='.-' read a b c
  575.                     echo $a.$b
  576.                 }
  577.     )"
  578.     KMINOR="$(uname -r |
  579.                 {
  580.                     IFS='.-' read a b c d
  581.                     # Strip any stuff from the end -- only the initial digits are part of the KMINOR.
  582.                     echo $c | sed -e 's/\([[:digit:]]*\).*/\1/'
  583.                 }
  584.     )"
  585.  
  586.     # Stop exporting everything -- what we do from here is private.
  587.     set +a
  588.  
  589.     if [ "$1" = "--version" ] ; then
  590.         log "MSG" "Laptop Mode Tools $LMTVERSION"
  591.         exit 0
  592.     fi
  593.  
  594.     if [ ! -e /proc/sys/vm/laptop_mode ] ; then
  595.         log "ERR" "Kernel does not have support for laptop mode. Please apply the laptop mode"
  596.         log "ERR" "patch or install a newer kernel."
  597.         exit 1
  598.     fi
  599.  
  600.     if [ ! -w /proc/sys/vm/laptop_mode ] ; then
  601.         log "ERR" "You do not have enough privileges to enable laptop_mode."
  602.         exit 1
  603.     fi
  604.  
  605.     INIT=0          # Display info in init script format?
  606.     FORCE=0         # Force reapplying the current state?
  607.     INITSCRIPT_STOP=0    # Track stop command from init script. Consumer is lm-polling daemon
  608.     while [ "$1" != "" ] ; do
  609.         case "$1" in 
  610.             init) INIT=1 ;;
  611.             force) FORCE=1 ;;
  612.             # Old options. We always do "auto" for any option now, but
  613.             # we still have to accept the options.
  614.             start) ;;
  615.             stop) INITSCRIPT_STOP=1 ;;
  616.             auto) ;;
  617.             modules=*)
  618.                 MODULES=$1
  619.                 MODULES=${MODULES#"modules="}
  620.                 ;;
  621.             devices=*)
  622.                 DEVICES=$1
  623.                 DEVICES=${DEVICES#"devices="}
  624.                 ;;
  625.             *) log "ERR" "Unrecognized option $1."
  626.               exit 1 ;;
  627.         esac
  628.         shift
  629.     done
  630.  
  631.     mkdir -p /var/run/laptop-mode-tools
  632.  
  633.     # Used to display laptop mode state later on. This is the enabled/disabled 
  634.     # state for laptop mode processing, it tells us nothing about whether laptop
  635.     # mode is actually _active_.
  636.     STATE=enabled
  637.     if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -eq 0 -a "$ENABLE_LAPTOP_MODE_ON_AC" -eq 0 -a "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -eq 0 ] ; then
  638.         STATE=disabled
  639.     fi
  640.  
  641.  
  642.     # Determine whether to activate or deactivate laptop mode.
  643.     ACTIVATE=0
  644.  
  645.     if [ "$ON_AC" -eq 1 ] ; then
  646.         if [ "$ENABLE_LAPTOP_MODE_ON_AC" -ne 0 ] ; then
  647.             log "VERBOSE" "On AC power: Activating, because ENABLE_LAPTOP_MODE_ON_AC is set."
  648.             ACTIVATE=1
  649.         else
  650.             log "VERBOSE" "On AC power: Deactivating, because ENABLE_LAPTOP_MODE_ON_AC is not set."
  651.             ACTIVATE=0
  652.         fi
  653.     else
  654.         if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -ne 0 ] ; then
  655.             log "VERBOSE" "On battery power: Activating, because ENABLE_LAPTOP_MODE_ON_BATTERY is set."
  656.             ACTIVATE=1
  657.         else
  658.             log "VERBOSE" "On battery power: Deactivating, because ENABLE_LAPTOP_MODE_ON_BATTERY is not set."
  659.             ACTIVATE=0
  660.         fi
  661.     fi
  662.  
  663.     if [ "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -ne 0 -a "$ACTIVATE" -eq 0 ] ; then
  664.         if [ -x "`which hal-find-by-property`" ] ; then
  665.             HAL_LID_BUTTON=$(hal-find-by-property --key "button.type" --string "lid")
  666.         fi
  667.         if [ "$HAL_LID_BUTTON" != "" ] ; then
  668.             HAL_LID_BUTTON_STATE=$(hal-get-property --udi $(hal-find-by-property --key "button.type" --string "lid") --key "button.state.value")
  669.             if [ "$HAL_LID_BUTTON_STATE" = "true" ] ; then
  670.                 log "VERBOSE" "Setting action to \"start\" because the lid is closed (says HAL)."
  671.                 ACTIVATE=1            
  672.             fi
  673.         elif [ -f /proc/acpi/button/lid/*/state ] ; then
  674.             if ( grep -q "closed" /proc/acpi/button/lid/*/state ) ; then
  675.                 log "VERBOSE" 'Setting action to "start" because the lid is closed (says /proc/acpi/button/lid/*/state).'
  676.                 ACTIVATE=1
  677.             fi
  678.         else
  679.             log "MSG" "Warning: ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED is set, but there is no file"
  680.             log "MSG" "/proc/acpi/button/lid/.../state, and hal information is not available either!"
  681.         fi
  682.     fi
  683.  
  684.     # If the init script has not been run or has been run with the "stop"
  685.     # argument, then we should never start laptop mode.
  686.     if [ ! -f /var/run/laptop-mode-tools/enabled ] ; then
  687.         log "VERBOSE" "Laptop mode disabled because /var/run/laptop-mode-tools/enabled is missing."
  688.         STATE=disabled
  689.     fi
  690.  
  691.     if [ "$ACTIVATE" -eq 1 -a -f /etc/default/laptop-mode ] ; then
  692.         . /etc/default/laptop-mode
  693.         if ! ( echo "$ENABLE_LAPTOP_MODE" |grep y ) ; then
  694.             log "VERBOSE" "Not starting laptop mode because it is disabled in /etc/default/laptop-mode."
  695.             STATE=disabled
  696.         fi
  697.     fi
  698.  
  699.     if [ "$STATE" = "disabled" ] ; then
  700.         ACTIVATE=0
  701.     fi
  702.  
  703.     # Check whether we are allowed to activate the data-loss-sensitive stuff.
  704.     # If the battery charge is too low, we want to disable this, but not the
  705.     # other power-saving stuff.
  706.  
  707.     if [ "$ACTIVATE" -eq 0 ] ; then
  708.         ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
  709.     elif [ "$ON_AC" = 1 ] ; then
  710.         log "VERBOSE" "On AC, not checking minimum battery charge."
  711.         ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1
  712.     else
  713.         ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1
  714.         ENOUGH_CHARGE=0
  715.         ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=0
  716.  
  717.         # Weird way of checking that /sys/class/power_supply is not empty -- but it works.
  718.         if [ "$(echo /sys/class/power_supply/*)" != '/sys/class/power_supply/*' ] ; then
  719.             log "VERBOSE" "Not on AC and we have battery information in /sys/class/power_supply/BAT* -- checking minimum battery charge."
  720.             for BATT in /sys/class/power_supply/* ; do
  721.                 BATT_TYPE=$(cat $BATT/type)
  722.                 log "VERBOSE" "$BATT is of type $BATT_TYPE."
  723.                 if [ "$BATT_TYPE" != "Battery" ] ; then
  724.                     log "VERBOSE" "Not of type \"Battery\", skipping."
  725.                 else
  726.                     PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE
  727.                     PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  728.  
  729.                     log "VERBOSE" "Checking levels for $BATT."
  730.                     PRESENT=$(cat $BATT/present)
  731.                     log "VERBOSE" "Present: $PRESENT."
  732.  
  733.                     # Only do if the battery is present
  734.                     if [ "$PRESENT" -eq 1 ] ; then
  735.                         FOUND_AN_ENABLED_CHECK=0
  736.                         FOUND_AN_ENABLED_HIBERNATION_CHECK=0
  737.                 
  738.                         # Get the remaining capacity.
  739.                         IN_UAH=0
  740.                         IN_UWH=0
  741.                         if [ -f $BATT/charge_now ] ; then                    
  742.                             REMAINING=$(cat $BATT/charge_now)
  743.                             IN_UAH=1 # charge_* is in microAmpere-hours
  744.                         elif [ -f $BATT/energy_now ] ; then
  745.                             REMAINING=$(cat $BATT/energy_now)
  746.                             IN_UWH=1 # energy_* is in microWatt-hours
  747.                         else
  748.                             REMAINING=0
  749.                         fi
  750.                         if [ -z "$REMAINING" -o "$REMAINING" -eq 0 ] ; then
  751.                             log "VERBOSE" "Battery does not report remaining charge. Perhaps it is not present?"
  752.                             REMAINING=0
  753.                         fi
  754.                         log "VERBOSE" "Remaining charge: $REMAINING"
  755.  
  756.                         if [ -f $BATT/charge_full_design ] ; then
  757.                             CAPACITY=$(cat $BATT/charge_full_design)
  758.                         elif [ -f $BATT/energy_full_design ] ; then
  759.                             CAPACITY=$(cat $BATT/energy_full_design)
  760.                         else
  761.                             CAPACITY=0
  762.                         fi
  763.                         if [ -z "$CAPACITY" -o "$CAPACITY" -eq 0 ] ; then
  764.                             log "VERBOSE" "Battery does not report design full charge, using non-design full charge."
  765.                             if [ -f $BATT/charge_full ] ; then
  766.                                 CAPACITY=$(cat $BATT/charge_full)
  767.                             elif [ -f $BATT/energy_full_design ] ; then
  768.                                 CAPACITY=$(cat $BATT/energy_full)
  769.                             else
  770.                                 CAPACITY=0
  771.                             fi
  772.                             if [ -z "$CAPACITY" -o "$CAPACITY" -eq 0 ] ; then
  773.                                 log "VERBOSE" "Battery does not report non-design full charge."    
  774.                                 CAPACITY=0
  775.                             fi
  776.                         fi
  777.                         log "VERBOSE" "Full capacity: $CAPACITY"
  778.  
  779.                         # Check the charge percentage
  780.                         if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  781.                             FOUND_AN_ENABLED_CHECK=1
  782.                             if [ "$CAPACITY" -eq 0 ] ; then
  783.                                 log "MSG" "WARNING: Battery does not report a capacity. Minimum battery"
  784.                                 log "MSG" "charge checking does not work without a design capacity."
  785.                                 ENOUGH_CHARGE=1
  786.                             elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
  787.                                 ENOUGH_CHARGE=1
  788.                             fi
  789.                         fi
  790.                         if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  791.                             FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  792.                             if [ "$CAPACITY" -eq 0 ] ; then
  793.                                 log "MSG" "WARNING: Battery does not report a design capacity. Auto hibernation"
  794.                                 log "MSG" "does not work without a design capacity."
  795.                                 ENOUGH_CHARGE=1
  796.                             elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
  797.                                 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  798.                             fi
  799.                         fi
  800.  
  801.                                             if [ -f $BATT/alarm ]; then
  802.                                                 # $BATT/alarm is the design_capacity_warning of a battery.
  803.                                                 ALARM_LEVEL=$(cat $BATT/alarm)
  804.                                             elif [ -f $BATT/energy_full ]; then
  805.                                                 # On Arm, it has been reported that there's no design_capacity_warning.
  806.                                                 # The design_capacity_warning is 5% of the energy_full value
  807.                                                 ENERGY_FULL=$(cat $BATT/energy_full)
  808.                                                 ALARM_LEVEL=$(expr $ENERGY_FULL \* 5 / 100)
  809.                                             else
  810.                                                 # If nothing is available, we don't want to touch hibernation.
  811.                                                 # We'll rather report it
  812.                                                 log "ERR" "You seem to have a broken battery"
  813.                                                 log "ERR" "Cannot determine design_capacity_warning"
  814.                                                 log "ERR" "Disabling hibernation"
  815.                                                 ENOUGH_CHARGE=1
  816.                                             fi
  817.  
  818.                         if [ "$ALARM_LEVEL" -ne 0 ] ; then
  819.                             if [ "$REMAINING" -le "$ALARM_LEVEL" ] ; then                
  820.                                 # Restore the state we had before checking this battery, so that
  821.                                 # this battery does not count as having enough charge.
  822.                                 ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE
  823.                             elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then
  824.                                 # This is the only check that is enabled. In that case a non-critical
  825.                                 # battery level counts as "enough". (If we would count non-critical
  826.                                 # battery levels as enough *always*, then the other settings would
  827.                                 # have no effect; this is only a final fallback.)
  828.                                 ENOUGH_CHARGE=1
  829.                             fi
  830.                         fi
  831.                         if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
  832.                             if [ "$REMAINING" -le "$ALARM_LEVEL" ] ; then                
  833.                                 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  834.                             elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then
  835.                                 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  836.                             fi
  837.                         fi
  838.                         
  839.                         #
  840.                         # Fallback: hard values
  841.                         #
  842.                         if [ "$IN_UAH" -ne 0 ] ; then
  843.                             if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  844.                                 FOUND_AN_ENABLED_CHECK=1
  845.                                 if [ "$REMAINING" -ge $((1000*"$MINIMUM_BATTERY_CHARGE_MAH")) ] ; then
  846.                                     ENOUGH_CHARGE=1
  847.                                 fi
  848.                             fi
  849.                             if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  850.                                 FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  851.                                 if [ "$REMAINING" -ge $((1000*"$AUTO_HIBERNATION_BATTERY_CHARGE_MAH")) ] ; then
  852.                                     ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  853.                                 fi
  854.                             fi
  855.                         elif [ "$IN_UWH" -ne 0 ] ; then
  856.                             if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  857.                                 FOUND_AN_ENABLED_CHECK=1
  858.                                 if [ "$REMAINING" -ge $((1000*"$MINIMUM_BATTERY_CHARGE_MWH")) ] ; then
  859.                                     ENOUGH_CHARGE=1
  860.                                 fi
  861.                             fi
  862.                             if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  863.                                 FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  864.                                 if [ "$REMAINING" -ge $((1000*"$AUTO_HIBERNATION_BATTERY_CHARGE_MWH")) ] ; then
  865.                                     ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  866.                                 fi
  867.                             fi
  868.                         else
  869.                             log "ERR" "Failed to determine battery charge. Battery charge units are not in"
  870.                             log "ERR" "mWh, uWh, mAh or uAh."
  871.                         fi
  872.                                             
  873.                     else
  874.                         log "VERBOSE" "Battery is not present."
  875.                     fi
  876.                 fi
  877.             done        
  878.         elif [ "$(echo /proc/acpi/battery/*)" != '/proc/acpi/battery/*' ] ; then
  879.             log "VERBOSE" "Not on AC and we have batteries in /proc/acpi/battery -- checking minimum battery charge."
  880.             for BATT in /proc/acpi/battery/* ; do
  881.                 PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE
  882.                 PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  883.  
  884.                 BATT_STATE=$BATT/state
  885.                 BATT_INFO=$BATT/info
  886.                 log "VERBOSE" "Checking info and state for $BATT."
  887.  
  888.                 # Only do if the battery is present
  889.                 if ( grep -q 'present:.*yes' $BATT_INFO ) ; then
  890.                     FOUND_AN_ENABLED_CHECK=0
  891.                     FOUND_AN_ENABLED_HIBERNATION_CHECK=0
  892.                 
  893.                     # Get the remaining capacity.
  894.                     REMAINING=`grep "remaining capacity:" $BATT_STATE | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
  895.                     if [ -z "$REMAINING" ] ; then
  896.                         log "VERBOSE" "Battery does not report remaining charte. Perhaps it is not present?"
  897.                         REMAINING=0
  898.                     fi
  899.                     log "VERBOSE" "Remaining charge: $REMAINING"
  900.  
  901.                     CAPACITY=`grep "design capacity:" $BATT_INFO | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
  902.                     if [ -z "$CAPACITY" ] ; then
  903.                         log "VERBOSE" "Battery does not report capacity. Perhaps it is not present?"
  904.                         CAPACITY=0
  905.                     fi
  906.                     log "VERBOSE" "Design capacity: $CAPACITY"
  907.  
  908.                     # Check the charge percentage
  909.                     if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  910.                         FOUND_AN_ENABLED_CHECK=1
  911.                         if [ "$CAPACITY" -eq 0 ] ; then
  912.                             log "MSG" "WARNING: Battery does not report a design capacity. Minimum battery"
  913.                             log "MSG" "charge checking does not work without a design capacity."
  914.                             ENOUGH_CHARGE=1
  915.                         elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
  916.                             ENOUGH_CHARGE=1
  917.                         fi
  918.                     fi
  919.                     if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  920.                         FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  921.                         if [ "$CAPACITY" -eq 0 ] ; then
  922.                             log "MSG" "WARNING: Battery does not report a design capacity. Auto hibernation"
  923.                             log "MSG" "does not work without a design capacity."
  924.                             ENOUGH_CHARGE=1
  925.                         elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
  926.                             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  927.                         fi
  928.                     fi
  929.  
  930.                     #
  931.                     # Fallback: hard values.
  932.                     #
  933.                     # Determine the reporting unit.
  934.                     IN_MAH=0
  935.                     IN_MWH=0
  936.                     if ( grep -q mWh $BATT_INFO ) ; then
  937.                         IN_MWH=1
  938.                     elif ( grep -q mAh $BATT_INFO ) ; then
  939.                         IN_MAH=1
  940.                     fi
  941.                 
  942.                     if [ "$IN_MAH" -ne 0 ] ; then
  943.                         if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  944.                             FOUND_AN_ENABLED_CHECK=1
  945.                             if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MAH" ] ; then
  946.                                 ENOUGH_CHARGE=1
  947.                             fi
  948.                         fi
  949.                         if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  950.                             FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  951.                             if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" ] ; then
  952.                                 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  953.                             fi
  954.                         fi
  955.                     elif [ "$IN_MWH" -ne 0 ] ; then
  956.                         if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  957.                             FOUND_AN_ENABLED_CHECK=1
  958.                             if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MWH" ] ; then
  959.                                 ENOUGH_CHARGE=1
  960.                             fi
  961.                         fi
  962.                         if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  963.                             FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  964.                             if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" ] ; then
  965.                                 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  966.                             fi
  967.                         fi
  968.                     else
  969.                         log "ERR" "Failed to determine battery charge. Battery charge units are not in"
  970.                         log "ERR" "mWh or mAh."
  971.                     fi
  972.                 
  973.                     CAP_STATE=`sed -r 's/^capacity state:\s*(.*)\s*$/\1/;t;d' "$BATT_STATE"`
  974.                     if [ "$DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
  975.                         if [ "$CAP_STATE" = "critical" ] ; then                
  976.                             # Restore the state we had before checking this battery, so that
  977.                             # this battery does not count as having enough charge.
  978.                             ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE
  979.                         elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then
  980.                             # This is the only check that is enabled. In that case a non-critical
  981.                             # battery level counts as "enough". (If we would count non-critical
  982.                             # battery levels as enough *always*, then the other settings would
  983.                             # have no effect; this is only a final fallback.)
  984.                             ENOUGH_CHARGE=1
  985.                         fi
  986.                     fi
  987.                     if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
  988.                         if [ "$CAP_STATE" = "critical" ] ; then                
  989.                             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  990.                         elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then
  991.                             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  992.                         fi
  993.                     fi
  994.                 else
  995.                     log "VERBOSE" "Battery is not present."
  996.                 fi
  997.             done
  998.         else
  999.             ENOUGH_CHARGE=1
  1000.             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  1001.             log "VERBOSE" "Not on AC and could not check battery state -- data loss sensitive features stay enabled and auto-hibernation will not work."
  1002.         fi
  1003.         if [ "$ENABLE_AUTO_HIBERNATION" -ne 0 -a "$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION" -eq 0 ] ; then
  1004.             log "VERBOSE" "None of the batteries have a charge above the auto-hibernation level."
  1005.             log "VERBOSE" "Starting hibernation."
  1006.             if [ -x $HIBERNATE_COMMAND ]; then
  1007.                 $HIBERNATE_COMMAND
  1008.             elif [ -f /sys/power/state ]; then
  1009.                 grep -q disk /sys/power/state && echo disk > /sys/power/state
  1010.             fi
  1011.  
  1012.             # Don't continue -- if things are configured correctly, then we
  1013.             # will be called on resume.
  1014.             exit 0            
  1015.         fi
  1016.         if [ "$ENOUGH_CHARGE" -eq 0 ] ; then
  1017.             log "VERBOSE" "None of the batteries have a charge above the minimum level."
  1018.             log "VERBOSE" "Deactivating data loss sensitive features."
  1019.             ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
  1020.         fi
  1021.     fi
  1022.  
  1023.     if [ "$INIT" -eq 0 ] ; then
  1024.         log "MSG" "Laptop mode "
  1025.     fi
  1026.  
  1027.     # WAS_ACTIVE is used later on. If there is no /var/run/laptop-mode-tools/state, then
  1028.     # we know that laptop mode wasn't active before.
  1029.     WAS_ACTIVE=0
  1030.     log "VERBOSE" "Checking if desired state is different from current state."
  1031.     if [ -f /var/run/laptop-mode-tools/state ] ; then
  1032.         read WAS_ACTIVE WAS_ON_AC WAS_ACTIVATE_WITH_POSSIBLE_DATA_LOSS WAS_STATE < /var/run/laptop-mode-tools/state
  1033.         if [ "$WAS_STATE" != "" ] ; then
  1034.             if [ "$WAS_ACTIVE" -eq "$ACTIVATE" -a "$WAS_ON_AC" -eq "$ON_AC" -a "$WAS_ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -a "$WAS_STATE" = "$STATE" -a "$FORCE" -eq 0 ] ; then
  1035.                 log "MSG" "$STATE, "
  1036.                 if [ "$WAS_ACTIVE" -eq 1 ] ; then
  1037.                     log "MSG" "active [unchanged]"
  1038.                     if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
  1039.                         log "MSG" " (Data-loss sensitive features disabled.)"
  1040.                     fi
  1041.                 else
  1042.                     log "MSG" "not active [unchanged]"
  1043.                 fi
  1044.                 exit 0
  1045.             fi
  1046.         fi
  1047.     else
  1048.         log "VERBOSE" "/var/run/laptop-mode-tools/state does not exist, no previous state."
  1049.     fi
  1050.     echo "$ACTIVATE $ON_AC $ACTIVATE_WITH_POSSIBLE_DATA_LOSS $STATE" > /var/run/laptop-mode-tools/state
  1051.  
  1052.     if [ "$ACTIVATE" -eq 1 ] ; then
  1053.         log "MSG" "$STATE, active"
  1054.         if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
  1055.             log "MSG" " (Data-loss sensitive features disabled.)"
  1056.         fi
  1057.     else
  1058.         log "MSG" "$STATE, not active"
  1059.     fi
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.     # Finally, call laptop-mode-tools modules. The modules can use the settings
  1066.     # from the config files, but they may NOT assume the settings actually exist,
  1067.     # as no defaults have been given for them.
  1068.  
  1069.     # Note that the /usr/local/lib path is deprecated.
  1070.     export FORCE STATE ON_AC ACTIVATE ACTIVATE_WITH_POSSIBLE_DATA_LOSS KLEVEL KMINOR WAS_ACTIVE LM_VERBOSE DEVICES
  1071.     for SCRIPT in /usr/share/laptop-mode-tools/modules/* /usr/local/lib/laptop-mode-tools/modules/* /usr/local/share/laptop-mode-tools/modules/* /etc/laptop-mode/modules/* ; do
  1072.         if [ -z "$MODULES" ] ; then
  1073.             # If a module list has not been provided, execute all modules
  1074.             EXECUTE_SCRIPT=1
  1075.         else
  1076.             # If a module list has been provided, execute only the listed
  1077.             # modules.
  1078.             EXECUTE_SCRIPT=0
  1079.             for MODULE in $MODULES; do
  1080.                 # Attempt to remove the module name from the end of the
  1081.                 # full script path.  If the module name matches the
  1082.                 # script, the name will be removed from the end of the
  1083.                 # full file path, leaving the path to the script.  If
  1084.                 # there was not a match made, the module name would not
  1085.                 # be removed from the path, and $PATH_TO_SCRIPT would
  1086.                 # be the same as $SCRIPT.
  1087.                 PATH_TO_SCRIPT=${SCRIPT%%$MODULE}
  1088.                 # Execute the script if a match was found (module name
  1089.                 # was removed from the script path, making it shorter.
  1090.                 if [ $PATH_TO_SCRIPT != $SCRIPT ] ; then
  1091.                     EXECUTE_SCRIPT=1
  1092.                 fi
  1093.             done
  1094.         fi
  1095.  
  1096.         if [ -x "$SCRIPT" -a $EXECUTE_SCRIPT -eq 1 ] ; then
  1097.             log "VERBOSE" "Invoking module $SCRIPT."
  1098.             SCRIPT_DEBUG=$SCRIPT; # We do this because in start-stop-programs module a $SCRIPT variable is used. That
  1099.                       # changes the whole meaning when passed to disableDebug ()
  1100.             enableDebug $SCRIPT_DEBUG;
  1101.             (. $SCRIPT) &
  1102.             disableDebug $SCRIPT_DEBUG;
  1103.         else
  1104.             log "VERBOSE" "Module $SCRIPT is not executable or is to be skipped."
  1105.         fi
  1106.     done
  1107.  
  1108.     # Wait for the forks to complete
  1109.     wait
  1110.  
  1111.     exit 0
  1112.  
  1113.     # This fi closes the if for "readconfig". If I would have indented this one
  1114.     # I would have indented the whole file. :)
  1115.     fi
  1116. }
  1117.  
  1118. lmt_load_config
  1119.  
  1120. # We do a special run of battery polling daemon here so that it does not get
  1121. # plagued by the lock. We need the polling daemon to be independent of the REQ and INVOC locks.
  1122. # Polling daemon should *only* have inherited a lock on LMT_BATTPOLL_LOCK. Any other inheritance
  1123. # for it is a BUG.
  1124. if [ x$ENABLE_BATTERY_LEVEL_POLLING = x1 ] && [ x$BLACKLIST_IN_FLOCK = x1 ]; then
  1125.     log "VERBOSE" "Battery level polling is enabled."
  1126.     if [ x$ON_AC = x1 ] ; then
  1127.         log "VERBOSE" "On AC, stopping the polling daemon."
  1128.  
  1129.         # In AC mode we disable the polling daemon.
  1130.         killall -q lm-polling-daemon
  1131.     elif [ x$ON_AC = x0 ]; then
  1132.         exec 7>$LMT_BATTPOLL_LOCK;
  1133.         if $FLOCK -n -x -w 1 7; then
  1134.             log "VERBOSE" "Lock acquisition on descriptor 7 succeeded with pid $$";
  1135.             if ! pidof -x lm-polling-daemon ; then
  1136.                 log "VERBOSE" "On battery and there was no polling daemon yet, starting the polling daemon."
  1137.             
  1138.                 # If there is no polling daemon, we start one.
  1139.                 /usr/share/laptop-mode-tools/module-helpers/lm-polling-daemon < /dev/null > /dev/null 2> /dev/null &
  1140.             fi
  1141.         else
  1142.             log "VERBOSE" "Lock acquisition on descriptor 7 failed with pid $$";
  1143.         fi
  1144.  
  1145.         # If we are called from the init script with the stop command, lm-polling-daemon
  1146.         # should be killed.
  1147.         if [ x$INITSCRIPT_STOP = x1 ]; then
  1148.             log "VERBOSE" "On Battery, but init script stop is called. Killing lm-polling-daemon"
  1149.             killall -q lm-polling-daemon
  1150.         fi
  1151.     else
  1152.         log "ERR" "Unknown ON_AC state: $ON_AC";
  1153.     fi
  1154. else
  1155.     log "VERBOSE" "Battery level polling is disabled."
  1156. fi
  1157.  
  1158. lock_retry ()
  1159. {
  1160. if $FLOCK -n -x -w 1 8; then
  1161.     i=10;
  1162.     while [ $i -ge 1 ]
  1163.     do
  1164.             $FLOCK -x -w 1 9 && lmt_main_function "$@" && break;
  1165.         log "VERBOSE" "Couldn't acquire lock on descriptor 9 in lock_retry(). Retrying.... PID is $$\n"
  1166.             i=$(( $i - 1 ))
  1167.     done
  1168. else
  1169.     exit 0;
  1170. fi
  1171. }
  1172.  
  1173.  
  1174. # Check and acquire locks and then exec.
  1175. exec 8>$LMT_REQ_LOCK;
  1176. if $FLOCK -n -x -w 1 8; then
  1177.     log "VERBOSE" "Prelim lock acquisition on descriptor 8 with pid $$";
  1178. else
  1179.     log "VERBOSE" "Couldn't acquire prelim lock on descriptor 8 with pid $$";
  1180. fi
  1181.  
  1182.  
  1183. exec 9>$LMT_INVOC_LOCK;
  1184. if $FLOCK -n -x -w 1 9; then
  1185.     $FLOCK -u 8; ## Release the invoc lock;
  1186.     log "VERBOSE" "Prelim lock acquisition on descriptor 9 with pid $$";
  1187.     log "VERBOSE" "Now invoking lmt_main_function with arguments -- $@";
  1188.     lmt_main_function "$@";
  1189. else
  1190.     log "VERBOSE" "Couldn't acquire prelim lock on descriptor 9 with pid $$";
  1191.     log "VERBOSE" "Now invoking lock_retry with arguments -- $@";
  1192.     lock_retry "$@";
  1193. fi
  1194.  
  1195. $FLOCK -u 8;
  1196. $FLOCK -u 9;
  1197.  
  1198.  
  1199. exit 0;
  1200.